/****************************
文件名:MapUtils.java
创建时间:2008-7-10 上午11:28:13
所在包:net.tycmc.cty.ctyms.timejob.common
作者:李晓凡
说明:地图相关计算
****************************/
package net.tycmc.cty.ctyms.timejob.common;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.tycmc.bulb.common.util.StringUtil;

import com.tycmc.functions.MapFunction;

public class MapUtils {

	//地球半径
	private static double EARTH_RADIUS = 6378.137;
	
	public static void main(String[] args) {
		Map<String,Object> targetPlace = new HashMap<String,Object>();
		targetPlace.put("lng", "114.622955322266");
		targetPlace.put("lat", "38.0451583862305");
		
		Map<String,Object> morePlace = new HashMap<String,Object>();
		//CTY测试1
		morePlace.put("radius", "773.731188932173");
		morePlace.put("lng", "114.682331");
		morePlace.put("lat", "38.01537");
		
		//CTY测试2
//		morePlace.put("radius", "502.158296736005");
//		morePlace.put("lng", "114.688125");
//		morePlace.put("lat", "37.991563");
		
		//TY测试门控1
//		morePlace.put("radius", "1214.88288665829");
//		morePlace.put("lng", "114.629288");
//		morePlace.put("lat", "38.047821");
		System.out.println(PointAndCircleRelationShip(targetPlace, morePlace));
	}
	
	/**
	 * 点与圆的位置关系
	 * @param targetPlace	车辆位置相关信息
	 * @param morePlace	围栏信息集合
	 * @return	0：车辆位置不存在或无围栏信息；1：点在圆内；2：点在圆外；3：点在圆上
	 */
	public static int PointAndCircleRelationShip(Map<String,Object> targetPlace,Map<String,Object> morePlace){
		if(targetPlace != null && targetPlace.size()>0 && morePlace != null && morePlace.size()>0){
			double radLat1 = rad(Double.parseDouble(targetPlace.get("lat").toString()));
			double radLat2 = rad(Double.parseDouble(morePlace.get("lat").toString()));
			double a = radLat1 - radLat2;
			double b = rad(Double.parseDouble(targetPlace.get("lng").toString())) - rad(Double.parseDouble(morePlace.get("lng").toString()));

			//计算两点之间的距离
			double d = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2)
					+ Math.cos(radLat1) * Math.cos(radLat2)
					* Math.pow(Math.sin(b / 2), 2)));
			d = d * EARTH_RADIUS * 1000;			//两点之间的距离单位：m
			float distance = Float.parseFloat(StringUtils.numberFormat((float)d));	//取两位小数（四舍五入）
			float r = Float.parseFloat(morePlace.get("radius").toString());	//	围栏半径
			
			//点与圆的位置关系（点在圆上，点在圆内，点在圆外）
			if(distance == r ){	//点在圆上
				return 3;
			}else if(distance > r){	//点在圆外
				return 2;
			}else if(distance < r){	//点在圆内
				return 1;
			}else{
				return 0;
			}
		}else{
			return 0;
		}
	}
	
	
	/**
	 * 点与圆的位置关系
	 * @param targetPlace	车辆位置相关信息
	 * @param morePlace	围栏信息集合
	 * @return	0：车辆位置不存在或无围栏信息；1：点在矩形内；2：点在矩形外；3：点在矩形上
	 */
	public static int PointAndSquareRelationShip(Map<String,Object> targetPlace,Map<String,Object> morePlace){
		if(targetPlace != null && targetPlace.size()>0 && morePlace != null && morePlace.size()>0){
			double radLatX = Double.parseDouble(targetPlace.get("lng").toString());  //经度
			double radLngY=Double.parseDouble(targetPlace.get("lat").toString());//纬度
			double OrgFen_RectLeftTX=Double.parseDouble(morePlace.get("OrgFen_RectLeftTX").toString());//左上经度
			double OrgFen_RectLeftTY = Double.parseDouble(morePlace.get("OrgFen_RectLeftTY").toString());//左上纬度
			double  OrgFen_RectRightBX= Double.parseDouble(morePlace.get("OrgFen_RectRightBX").toString());//右下经度
			double OrgFen_RectRightBY = Double.parseDouble(morePlace.get("OrgFen_RectRightBY").toString());//右下纬度
			//根据经纬度判断位置//点与圆的位置关系 1点在矩形内；2：点在矩形外；3：点在矩形边上
			if((radLatX==OrgFen_RectLeftTX||radLatX==OrgFen_RectRightBX)&&(pointIn(radLngY,OrgFen_RectLeftTY,OrgFen_RectRightBY))){//边上
				return 3;
			}else if((radLngY==OrgFen_RectLeftTY||radLngY==OrgFen_RectRightBY)&&pointIn(radLatX,OrgFen_RectLeftTX,OrgFen_RectRightBX)){//边上
				return 3;
			}else if(pointIn(radLngY,OrgFen_RectLeftTY,OrgFen_RectRightBY)&&pointIn(radLatX,OrgFen_RectLeftTX,OrgFen_RectRightBX)){//矩形内
				return 1;
			}else if(pointIn(radLngY,OrgFen_RectLeftTY,OrgFen_RectRightBY)==false||pointIn(radLatX,OrgFen_RectLeftTX,OrgFen_RectRightBX)==false){//矩形外
				return 2;
			}else{
				return 0;
			}
		}else{
			return 0;
		}
	}
	private static double rad(double d) {
		return d * Math.PI / 180.0;
	}
	/** 
	 * 判断一个点在两点之间
	 * SXh
	 * @param a：要判断的点 ,b:范围点中的一点 c:范围点中的另一点
	 * @return boolean  true 两点之间
	 * */
	private static boolean pointIn(double a,double b,double c) {
		double d= (a-b)*(c-a);
		if(d>0){
			return true;
		}else{
			return false;
		}
	}
	/**********一下是点与多边形的位置关系******************BEGIN*******************************************/
//	public static void main(String[] args) {
//
//		double px = 113.0253;
//		double py = 23.98049;
//		ArrayList<Double> polygonXA = new ArrayList<Double>();
//		ArrayList<Double> polygonYA = new ArrayList<Double>();
//		polygonXA.add(113.0253);
//		polygonXA.add(113.4121);
//		polygonXA.add(113.37109);
//		polygonXA.add(113.02148);
//		// 113.18359,23.8496
//		// 113.0253,23.98049 113.4121,23.9687 113.37109,2.73828
//		// 113.02148,23.7539C
//		polygonYA.add(23.98049);
//		polygonYA.add(23.9687);
//		polygonYA.add(23.73828);
//		polygonYA.add(23.7539);
//		System.out.println(MapUtils.isPointInPolygon(px, py, polygonXA, polygonYA));
//	}

	public static boolean isPointInPolygon(double px, double py,
			ArrayList<Double> polygonXA, ArrayList<Double> polygonYA) {
		boolean isInside = false;
		double ESP = 1e-9;
		int count = 0;
		double linePoint1x;
		double linePoint1y;
		double linePoint2x = 180;
		double linePoint2y;
		linePoint1x = px;
		linePoint1y = py;
		linePoint2y = py;
		for (int i = 0; i < polygonXA.size() - 1; i++) {
			double cx1 = polygonXA.get(i);
			double cy1 = polygonYA.get(i);
			double cx2 = polygonXA.get(i + 1);
			double cy2 = polygonYA.get(i + 1);
			if (isPointOnLine(px, py, cx1, cy1, cx2, cy2)) {
				return true;
			}

			if (Math.abs(cy2 - cy1) < ESP) {
				continue;
			}

			if (isPointOnLine(cx1, cy1, linePoint1x, linePoint1y, linePoint2x,
					linePoint2y)) {
				if (cy1 > cy2)
					count++;
			} else if (isPointOnLine(cx2, cy2, linePoint1x, linePoint1y,
					linePoint2x, linePoint2y)) {
				if (cy2 > cy1)
					count++;
			} else if (isIntersect(cx1, cy1, cx2, cy2, linePoint1x,
					linePoint1y, linePoint2x, linePoint2y)) {
				count++;
			}
		}
		if (count % 2 == 1) {
			isInside = true;
		}
		return isInside;
	}

	public static double Multiply(double px0, double py0, double px1, double py1,
			double px2, double py2) {
		return ((px1 - px0) * (py2 - py0) - (px2 - px0) * (py1 - py0));
	}

	public static boolean isPointOnLine(double px0, double py0, double px1,
			double py1, double px2, double py2) {
		boolean flag = false;
		double ESP = 1e-9;
		if ((Math.abs(Multiply(px0, py0, px1, py1, px2, py2)) < ESP)
				&& ((px0 - px1) * (px0 - px2) <= 0)
				&& ((py0 - py1) * (py0 - py2) <= 0)) {
			flag = true;
		}
		return flag;
	}

	public static boolean isIntersect(double px1, double py1, double px2, double py2,
			double px3, double py3, double px4, double py4) {
		boolean flag = false;
		double d = (px2 - px1) * (py4 - py3) - (py2 - py1) * (px4 - px3);
		if (d != 0) {
			double r = ((py1 - py3) * (px4 - px3) - (px1 - px3) * (py4 - py3))
					/ d;
			double s = ((py1 - py3) * (px2 - px1) - (px1 - px3) * (py2 - py1))
					/ d;
			if ((r >= 0) && (r <= 1) && (s >= 0) && (s <= 1)) {
				flag = true;
			}
		}
		return flag;
	}
	/**********一下是点与多边形的位置关系******************BEGIN*******************************************/

	/**
	 * 获取位置
	 * @param vclLoLaList 经纬度数组
	 * @param loc  中英文
	 * @return
	 */
	public static List<String[]> getPositionPromt(List<String[]> vclLoLaList,String loc) {
		
		String loStrs = "";				//定义多组经度
		String laStrs = "";				//定义多组维度
		
		//定义有经度维度的列表
		List<String[]> existsLola = new ArrayList<String[]>();
		
		//循环精度纬度 分割为   有经度维度的existsLola列表和没有经度维度的noExistsLola列表
		for(String[] vclStr : vclLoLaList){
			if(!"undefined".equals(vclStr[0])){
				if(vclStr[1].equals("0.0")||vclStr[2].equals("0.0") || !StringUtil.isValid(vclStr[1]) || !StringUtil.isValid(vclStr[2])){
					//
				}else{
					existsLola.add(vclStr);
				}
			}
		}
		
		//拼接多组经纬度，调用地图服务
		if(existsLola.size()>0){
			for(int i=0;i<existsLola.size();i++){ 
				loStrs += existsLola.get(i)[1].toString()+",";
				laStrs  += existsLola.get(i)[2].toString()+",";
			}
			loStrs  = loStrs.substring(0,loStrs.length()-1);
			laStrs  = laStrs.substring(0,laStrs.length()-1);
		}
		
		//调用服务获得位置（分隔的位置信息，无位置信息则为""）
		String vclPositions = "";
		try{
			if(loStrs.length()>0){
				vclPositions = MapFunction.getPositionReviseNoReplaceDescription(loStrs, laStrs);
			}
		}catch(Exception ex){
			//调用出错
			System.out.print("调用地图服务获得位置出错，" +
					"代码位置：TeamOverViewListService.getPositionPromt(List<String[]> vclLoLaList,String loc)");
		}
		
		//分割地图并封装
		String[] vclPositionArr = new String[vclLoLaList.size()];
		vclPositionArr = vclPositions.split(",");
		
		//设备和设备位置集合 String[0] 设备号，String[1] 设备位置
		List<String[]> vclPositionList = new ArrayList<String[]>();
		//循环获得的地图位置 添加入返回集合 vclPositionList
		for(int j=0;j<existsLola.size();j++){
			String[] position = new String[2];
			position[0] = existsLola.get(j)[0];
			
			//封装地图位置
			String vclPos = "";
			//验证数组下标
			if(vclPositionArr.length>=j+1){
				vclPos =  vclPositionArr[j];
			}
			//验证是否为空
			if(!StringUtil.isNullOrEmpty(vclPos)){
				continue;
			}
			position[1] = vclPos;
			vclPositionList.add(position);
		}
		
		return vclPositionList;
	}
}

